#include <stdlib.h>
#include <iostream>
#include <initializer_list>
#include <vector>
#include <ostream>
using namespace std;
struct Student
{
    std::string name;
    int id;
    std::vector<double> scores;
};

ostream &operator<<(ostream &os, const Student &stu)
{
    os << stu.name << " : " << stu.id << " ";
    for (auto x : stu.scores)
    {
        os << x << " ";
    }
    return os;
}

istream &operator>>(istream &is, Student &stu)
{
    is >> stu.name >> stu.id;
    double x;
    while (is >> x)
    {
        stu.scores.push_back(x);
    }
    return is;
}

using namespace std;

struct Node_base
{
    Node_base *succ = nullptr;
    void insert_after(Node_base *n);
    void erase_after();
};
void Node_base::insert_after(Node_base *n)
{
    n->succ = succ;
    succ = n;
}
void Node_base::erase_after()
{
    if (succ)
    {
        succ = succ->succ;
    }
}

template <class T>
struct Node : public Node_base
{
    Node(const T &val) : Node_base{}, _val(val) {}
    T _val;
};

template <class T>
struct slist_iterator
{
    slist_iterator() {}
    slist_iterator(Node_base *n) : pos(n) {}
    slist_iterator &operator++()
    {
        pos = pos->succ;
        return *this;
    }
    T *operator->() const
    {
        return &static_cast<Node<T> *>(pos)->_val;
    }
    T &operator*() const
    {
        return static_cast<Node<T> *>(pos)->_val;
    }
    bool operator==(const slist_iterator &n) const
    {
        return pos == n.pos;
    }
    bool operator!=(const slist_iterator &n) const
    {
        return pos != n.pos;
    }
    Node_base *pos;
};

template <class T>
class slist
{
public:
    using iterator = slist_iterator<T>;
    using pointer = T *;
    slist() : _sz(0) {};
    slist(const slist<T> &li);
    slist(initializer_list<T> &list)
    {
        insert_after(begin_after(), list.begin(), list.end());
    }
    ~slist() { clear(); }
    void push_front(const T &val);
    iterator pop_front();
    T &front();
    bool empty() { return _sz == 0; }
    void clear();
    iterator begin() const
    {
        return iterator(_head.succ);
    }
    iterator begin_after()
    {
        return iterator(&_head);
    }
    iterator end() const
    {
        return iterator(nullptr);
    }
    iterator erase_after(iterator p);
    template <class Iter>
    iterator insert_after(iterator pos, Iter first, Iter last);
    iterator push_back(const T &val);
    slist<T> &operator=(const slist<T> &li);

private:
    Node_base _head;
    size_t _sz;
};

template <class T>
slist<T> &slist<T>::operator=(const slist<T> &li)
{
    clear();
    for (auto x : li)
    {
        push_back(x);
    }
    return *this;
}

template <class T>
slist<T>::slist(const slist<T> &li)
{
    for (auto x : li)
    {
        push_back(x);
    }
}
template <class T>
typename slist<T>::iterator slist<T>::erase_after(iterator p)
{
    iterator next = p.pos->succ;
    p.pos->erase_after();
    delete static_cast<Node<T> *>(next.pos);
    return iterator(p.pos->succ);
    --_sz;
}

template <class T>
typename slist<T>::iterator slist<T>::push_back(const T &val)
{
    iterator cur = iterator(&_head);
    Node<T> *new_node = new Node<T>(val);
    while (cur.pos->succ)
    {
        cur.pos = cur.pos->succ;
    }
    cur.pos->succ = new_node;
    _sz++;
    return iterator(new_node);
}

template <class T>
void slist<T>::push_front(const T &val)
{
    Node<T> *new_node = new Node<T>(val);
    _head.insert_after(new_node);
    ++_sz;
}
template <class T>
typename slist<T>::iterator slist<T>::pop_front()
{
    Node_base *ret = nullptr;
    if (_head.succ)
    {
        Node_base *next = _head.succ->succ;
        delete static_cast<Node<T> *>(_head.succ);
        _head.succ = next;
        --_sz;
    }
    return iterator(ret);
}

template <class T>
T &slist<T>::front()
{
    return static_cast<Node<T> *>(_head.succ)->_val;
}

template <class T>
void slist<T>::clear()
{
    while (_head.succ)
    {
        Node_base *next = _head.succ->succ;
        delete static_cast<Node<T> *>(_head.succ);
        _head.succ = next;
    }
    _sz = 0;
}
template <class T>
template <class Iter>
typename slist<T>::iterator slist<T>::insert_after(iterator pos, Iter first, Iter last)
{
    iterator next = nullptr;
    iterator cur = pos;
    int index = last - first;
    if (cur.pos->succ)
    {
        next = cur.pos->succ;
    }
    while (first != last)
    {
        Node<T> *new_node = new Node<T>(*first);
        cur.pos->succ = new_node;
        cur = cur.pos->succ;
        first++;
    }
    cur.pos->succ = next.pos;
    _sz += index;
    return iterator(cur.pos->succ);
}

int main()
{
    initializer_list<int> list{1, 2, 3, 4, 5};
    slist<int> test(list);
    slist<int> test2 = test;
    for (auto &x : test2)
    {
        cout << x << " ";
    }
}